package com.liao.rent.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liao.rent.constant.RedisConstant;
import com.liao.rent.constant.ResultCode;
import com.liao.rent.dto.SysUserDto;
import com.liao.rent.entity.JsonResult;
import com.liao.rent.entity.SysUser;
import com.liao.rent.entity.SysUserDetails;
import com.liao.rent.mapper.SysUserMapper;
import com.liao.rent.service.RedisService;
import com.liao.rent.service.SysUserService;
import com.liao.rent.utils.JwtUtil;
import com.liao.rent.utils.ResultTool;
import com.liao.rent.vo.LoginVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author liao
 * @since 2024-11-24
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService, UserDetailsService {

    @Autowired
    SysUserMapper sysUserMapper;

    @Autowired
    JwtUtil jwtUtil;

    @Lazy
    @Autowired
    PasswordEncoder bCryptPasswordEncoder;

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    RedisService redisService;



    //创建用户
    @Override
    public Boolean createUser(SysUser user) {
//        判断用户名是否为空
        boolean empty = StringUtils.isEmpty(user.getAccount());
        if (empty) {
            return false;
        }
        //查询用户名是否重复
       Boolean isExits= checkAccout(user.getAccount());


       if (isExits) {
           return false;
       }



        //查询手机号是否重复
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper1.eq(SysUser::getPhone, user.getPhone());

        SysUser sysUser1 = getOne(sysUserLambdaQueryWrapper1);
        if (sysUser1 != null) {
            return false;
        }



        //将用户信息保存到数据库中
        user.setPassword("{bcrypt}" + bCryptPasswordEncoder.encode(user.getPassword()));
        save(user);


        return true;
    }


    /**
     * 查询是否存在对象
     * @param account
     * @return
     */
    private Boolean checkAccout(String account) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getAccount, account);
       Long count= sysUserMapper.selectCount(wrapper);
       return count>0;
    }

    /**
     * 登录
     * @param vo 登录接收的参数
     * @return
     */
    @Override
    public JsonResult login(LoginVo vo) {
//        获得用户名和参数密码
        String account = vo.getAccount();
        String password = vo.getPassword();

//        获取UsernamePasswordAuthenticationToken 创建用户密码验证token对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account, password);

        try {
            //添加到验证管理器进行验证
            Authentication authRequest = authenticationManager.authenticate(authenticationToken);

            if (authRequest.isAuthenticated()) {
//                归还到secrurityContext中
                SecurityContextHolder.getContext().setAuthentication(authRequest);
//                生成jwtToken
                String key = RedisConstant.USER_Prefix + ((SysUserDetails) authRequest.getPrincipal()).getUser().getId();
                String jwtToken = jwtUtil.generateToken(key);

                redisService.set(key, authRequest.getPrincipal(), 60 * 60 * 12 * 7);


                return new JsonResult(true, jwtToken);
            }
        } catch (Exception e) {
//            log.error("登录失败", e);
            return ResultTool.fail(e.getMessage());
        }

        return ResultTool.fail(ResultCode.USER_CREDENTIALS_ERROR);
    }


    /**
     * 退出登录
     * @return
     */
    @Override
    public JsonResult logout() {
//从安全上下文中获取当前用户对象
        SysUserDetails userDetails = (SysUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        组装redis的key
        String key = RedisConstant.USER_Prefix + userDetails.getUser().getId();
//        删除redis中的token
        redisService.del(key);
//        清除安全上下文
        SecurityContextHolder.clearContext();


        return ResultTool.success("退出成功");
    }

    @Override
    public JsonResult<SysUser> getUserInfo() {
//        获取当前用户信息
        SysUserDetails userDetails = (SysUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUser user = userDetails.getUser();

//在从数据库中查询最新的用户数据返回
        user= getById(user.getId());
        user.setPassword("");
        return ResultTool.success(user);
    }

    /**
     * 返回用户信息
     * @param page 页码
     * @param size 每页大小
     * @param name 查询的关键字
     * @return
     */
    @Override
    public JsonResult<Page<SysUserDto>> List(int page, int size, String name) {
        // 构造分页构造器
        Page<SysUser> pageInfo = new Page(page, size);
        Page<SysUserDto> SysUserDtoPage=new Page<>();

        // 构造条件
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.isNotEmpty(name), SysUser::getAccount, name)
                .or().like(StringUtils.isNotEmpty(name), SysUser::getUserName, name)
                .or().like(StringUtils.isNotEmpty(name), SysUser::getPhone, name);
        // 添加排序
        queryWrapper.orderByAsc(SysUser::getId);


        // 执行查询
        Page<SysUser> sysUserPage = sysUserMapper.selectPage(pageInfo, queryWrapper);


//得到用户对象集合
        List<SysUser> sysUsers = sysUserPage.getRecords();
//       sysUsers.stream().peek(sysUser -> sysUser.setPassword("")).toList();
//        stream流遍历获取用户角色，装载dto对象
        List<SysUserDto> sysUserDtoList = sysUsers.stream().map(sysUser -> {
            sysUser.setPassword(null);
            SysUserDto userDto = new SysUserDto();
            BeanUtils.copyProperties(sysUser, userDto);
            //获取用户角色
            Integer roleId = sysUserMapper.selectRoleIdByUserId(sysUser.getId());
            userDto.setRoleId(roleId);


            return userDto;

        }).collect(Collectors.toList());

//        sysUserPage.setRecords(sysUsers);
        //重新装填分页数据
        SysUserDtoPage.setRecords(sysUserDtoList);
        SysUserDtoPage.setTotal(sysUserPage.getTotal());
        SysUserDtoPage.setCurrent(sysUserPage.getCurrent());
        SysUserDtoPage.setSize(sysUserPage.getSize());
        SysUserDtoPage.setPages(sysUserPage.getPages());
        return ResultTool.success(SysUserDtoPage);
    }

    /**
     *
     * 修改密码
     */
//    @Override
//    public JsonResult updatePassword(String oldPassword, String newPassword) {
//        SysUserDetails userDetails = (SysUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//    }


    /**
     * 管理员修改用户密码
     * @param userId
     * @param newPassword
     * @return 是否更新成功
     */

    @Override
    public Boolean updatePasswordById(Integer userId, String newPassword) {

        if ( StringUtils.isEmpty(newPassword)) {
            return false;
        }

        SysUser sysUser = new SysUser();

        sysUser.setId(userId);
//        加密处理密码
        newPassword=bCryptPasswordEncoder.encode(newPassword);
        sysUser.setPassword(newPassword);

        int update = sysUserMapper.updateById(sysUser);

        return update > 0;

    }

    @Override
    public Boolean updateRoleIdBYUserId(Integer userId, Integer roleId) {

        return sysUserMapper.updateRoleIdByUserId(userId, roleId) > 0;
    }

    @Override
    public Boolean createRoleIdBYUserId(Integer userId, Integer roleId) {
        return sysUserMapper.createRoleIdByUserId(userId, roleId) > 0;
    }

    @Override
    public Boolean deleteRoleIdBYUserId(Integer userId) {
        return sysUserMapper.deleteRoleIdByUserId(userId) > 0;
    }

    @Override
    public List<String> getUserAuthorities(Integer userId) {
        List<String> authorities = sysUserMapper.selectAuthoritiesByUserId(userId);
        return authorities;
    }


    /**
     * secrity 安全认证检查方法
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//        根据用户名查询用户信息
        LambdaQueryWrapper<SysUser> queryWrapper = new QueryWrapper<SysUser>().lambda().eq(SysUser::getAccount, username);
        SysUser sysUser = getOne(queryWrapper);

        if (sysUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        //获取用户权限
        List<String> authorities = sysUserMapper.selectAuthoritiesByUserId(sysUser.getId());

        UserDetails userDetails = new SysUserDetails(sysUser,authorities);
        return userDetails;
    }


}
